"""
插件管理器

统一管理插件的生命周期、依赖关系和执行。
"""

import asyncio
import logging
from typing import Dict, List, Optional, Any, Set, Callable
import threading
from pathlib import Path

from .base import Plugin, PluginMetadata, PluginState
from .loader import PluginLoader, default_loader
from .registry import PluginRegistry, plugin_registry
from .context import PluginContext
from .hooks import HookManager, hook_manager as global_hook_manager
from .exceptions import (
    PluginError, PluginLoadError, PluginNotFoundError,
    PluginDependencyError, PluginInitializationError
)


class PluginManager:
    """
    插件管理器
    
    统一管理插件的加载、初始化、执行和卸载。
    """
    
    def __init__(self, 
                 context: Optional[PluginContext] = None,
                 registry: Optional[PluginRegistry] = None,
                 loader: Optional[PluginLoader] = None,
                 hook_manager: Optional[HookManager] = None):
        self.context = context or PluginContext()
        self.registry = registry or plugin_registry
        self.loader = loader or default_loader
        self.hook_manager = hook_manager or global_hook_manager
        
        # 配置日志
        self.logger = logging.getLogger(self.__class__.__name__)
        
        # 插件生命周期回调
        self._load_callbacks: List[Callable[[Plugin], None]] = []
        self._unload_callbacks: List[Callable[[Plugin], None]] = []
        self._error_callbacks: List[Callable[[Plugin, Exception], None]] = []
        
        # 线程锁
        self._lock = threading.RLock()
        
        # 初始化状态
        self._initialized = False
    
    async def initialize(self) -> None:
        """初始化插件管理器"""
        if self._initialized:
            return
        
        
        # 注册核心钩子点
        self._register_core_hooks()
        
        # 设置插件上下文服务
        self.context.register_service("plugin_manager", self)
        self.context.register_service("plugin_registry", self.registry)
        self.context.register_service("hook_manager", self.hook_manager)
        
        self._initialized = True
    
    def _register_core_hooks(self) -> None:
        """注册核心钩子点"""
        core_hooks = [
            ("plugin.before_load", "插件加载前"),
            ("plugin.after_load", "插件加载后"),
            ("plugin.before_init", "插件初始化前"),
            ("plugin.after_init", "插件初始化后"),
            ("plugin.before_execute", "插件执行前"),
            ("plugin.after_execute", "插件执行后"),
            ("plugin.before_unload", "插件卸载前"),
            ("plugin.after_unload", "插件卸载后"),
            ("plugin.on_error", "插件错误时"),
            ("workflow.before_compile", "工作流编译前"),
            ("workflow.after_compile", "工作流编译后"),
            ("workflow.before_execute", "工作流执行前"),
            ("workflow.after_execute", "工作流执行后"),
        ]
        
        for hook_name, description in core_hooks:
            self.hook_manager.register_hook_point(hook_name, description)
    
    async def load_plugin(self, source: str, auto_init: bool = True) -> Plugin:
        """
        加载插件
        
        Args:
            source: 插件源（文件路径、包名等）
            auto_init: 是否自动初始化
        
        Returns:
            加载的插件实例
        """
        with self._lock:
            try:
                # 执行加载前钩子
                await self.hook_manager.execute_before_hooks(
                    "plugin.before_load", 
                    {"source": source}
                )
                
                # 加载插件
                plugin = self.loader.load_plugin(source)
                
                # 设置插件上下文
                plugin.context = self.context
                plugin.logger = self.context.get_logger(plugin.name)
                
                # 加载插件配置
                plugin_config = self.context.load_plugin_config(plugin.name)
                plugin.update_config(plugin_config)
                
                # 验证配置
                config_errors = plugin.validate_config()
                if config_errors:
                    raise PluginInitializationError(
                        f"插件配置验证失败: {', '.join(config_errors)}",
                        plugin_name=plugin.name
                    )
                
                # 注册插件
                self.registry.register(plugin, plugin.metadata)
                
                # 执行加载后钩子
                await self.hook_manager.execute_after_hooks(
                    "plugin.after_load",
                    {"source": source, "plugin": plugin},
                    plugin
                )
                
                # 触发加载回调
                for callback in self._load_callbacks:
                    try:
                        callback(plugin)
                    except Exception as e:
                        self.logger.error(f"加载回调执行失败: {e}")
                
                # 自动初始化
                if auto_init:
                    await self.initialize_plugin(plugin.name)
                
                return plugin
                
            except Exception as e:
                self.logger.error(f"插件加载失败: {source}, 错误: {e}")
                
                # 执行错误钩子
                await self.hook_manager.execute_error_hooks(
                    "plugin.on_error",
                    {"source": source, "error": e},
                    e
                )
                
                raise
    
    async def load_plugins_from_directory(self, directory: str, auto_init: bool = True) -> List[Plugin]:
        """从目录批量加载插件"""
        directory_path = Path(directory)
        if not directory_path.exists():
            raise PluginNotFoundError(f"插件目录不存在: {directory}")
        
        plugins = []
        plugin_sources = self.loader.discover_plugins(directory)
        
        
        for source in plugin_sources:
            try:
                plugin = await self.load_plugin(source, auto_init=False)
                plugins.append(plugin)
            except Exception as e:
                self.logger.error(f"加载插件失败: {source}, 错误: {e}")
                continue
        
        # 按依赖顺序初始化
        if auto_init and plugins:
            await self.initialize_plugins([p.name for p in plugins])
        
        return plugins
    
    async def initialize_plugin(self, plugin_name: str) -> None:
        """初始化插件"""
        plugin = self.registry.get_plugin(plugin_name)
        if not plugin:
            raise PluginNotFoundError(f"插件未找到: {plugin_name}")
        
        if plugin.state != PluginState.LOADED:
            self.logger.warning(f"插件状态不正确，无法初始化: {plugin_name} (状态: {plugin.state})")
            return
        
        try:
            # 检查依赖
            await self._check_and_load_dependencies(plugin_name)
            
            # 执行初始化前钩子
            await self.hook_manager.execute_before_hooks(
                "plugin.before_init",
                {"plugin_name": plugin_name, "plugin": plugin}
            )
            
            # 初始化插件
            await plugin.on_init(self.context)
            
            # 更新状态
            plugin.set_state(PluginState.INITIALIZED)
            
            # 执行初始化后钩子
            await self.hook_manager.execute_after_hooks(
                "plugin.after_init",
                {"plugin_name": plugin_name, "plugin": plugin},
                None
            )
            
            
        except Exception as e:
            plugin.set_state(PluginState.ERROR)
            self.logger.error(f"插件初始化失败: {plugin_name}, 错误: {e}")
            
            # 触发错误回调
            for callback in self._error_callbacks:
                try:
                    callback(plugin, e)
                except Exception as callback_error:
                    self.logger.error(f"错误回调执行失败: {callback_error}")
            
            raise PluginInitializationError(
                f"插件初始化失败: {e}",
                plugin_name=plugin_name,
                cause=e
            )
    
    async def initialize_plugins(self, plugin_names: Optional[List[str]] = None) -> None:
        """批量初始化插件"""
        if plugin_names is None:
            plugin_names = self.registry.list_plugins(state=PluginState.LOADED)
        
        # 获取加载顺序
        load_order = self.registry.get_load_order(plugin_names)
        
        for plugin_name in load_order:
            await self.initialize_plugin(plugin_name)
    
    async def _check_and_load_dependencies(self, plugin_name: str) -> None:
        """检查并加载插件依赖"""
        metadata = self.registry.get_metadata(plugin_name)
        if not metadata:
            return
        
        missing_dependencies = []
        
        for dependency in metadata.dependencies:
            if not self.registry.has_plugin(dependency):
                missing_dependencies.append(dependency)
            else:
                # 确保依赖已初始化
                dep_plugin = self.registry.get_plugin(dependency)
                if dep_plugin and dep_plugin.state == PluginState.LOADED:
                    await self.initialize_plugin(dependency)
        
        if missing_dependencies:
            raise PluginDependencyError(
                f"插件 {plugin_name} 缺少依赖: {', '.join(missing_dependencies)}",
                plugin_name=plugin_name,
                missing_dependencies=missing_dependencies
            )
    
    async def unload_plugin(self, plugin_name: str) -> bool:
        """卸载插件"""
        with self._lock:
            plugin = self.registry.get_plugin(plugin_name)
            if not plugin:
                return False
            
            try:
                # 执行卸载前钩子
                await self.hook_manager.execute_before_hooks(
                    "plugin.before_unload",
                    {"plugin_name": plugin_name, "plugin": plugin}
                )
                
                # 销毁插件
                await plugin.on_destroy()
                
                # 注销插件钩子
                self.hook_manager.unregister_plugin_hooks(plugin_name)
                
                # 从注册表移除
                self.registry.unregister(plugin_name)
                
                # 执行卸载后钩子
                await self.hook_manager.execute_after_hooks(
                    "plugin.after_unload",
                    {"plugin_name": plugin_name, "plugin": plugin},
                    True
                )
                
                # 触发卸载回调
                for callback in self._unload_callbacks:
                    try:
                        callback(plugin)
                    except Exception as e:
                        self.logger.error(f"卸载回调执行失败: {e}")
                
                return True
                
            except Exception as e:
                self.logger.error(f"插件卸载失败: {plugin_name}, 错误: {e}")
                plugin.set_state(PluginState.ERROR)
                raise
    
    async def reload_plugin(self, plugin_name: str) -> Plugin:
        """重新加载插件"""
        # 获取插件源信息
        plugin = self.registry.get_plugin(plugin_name)
        if not plugin:
            raise PluginNotFoundError(f"插件未找到: {plugin_name}")
        
        # 保存配置
        plugin_config = plugin.config.copy()
        
        # 卸载插件
        await self.unload_plugin(plugin_name)
        
        # 重新加载（这里需要保存原始源信息）
        # 简化实现，实际需要保存插件源路径
        raise NotImplementedError("插件重新加载功能需要保存插件源信息")
    
    def get_plugin(self, plugin_name: str) -> Optional[Plugin]:
        """获取插件实例"""
        return self.registry.get_plugin(plugin_name)
    
    def list_plugins(self, **filters) -> List[str]:
        """列出插件"""
        return self.registry.list_plugins(**filters)
    
    def get_plugin_info(self, plugin_name: str) -> Optional[Dict[str, Any]]:
        """获取插件信息"""
        plugin = self.registry.get_plugin(plugin_name)
        metadata = self.registry.get_metadata(plugin_name)
        
        if not plugin:
            return None
        
        return {
            "name": plugin.name,
            "version": plugin.version,
            "state": plugin.state.value,
            "description": plugin.description,
            "author": plugin.author,
            "metadata": metadata.to_dict() if metadata else None,
            "config": plugin.config,
            "dependencies": self.registry.get_dependencies(plugin_name),
            "dependents": self.registry.get_dependents(plugin_name),
        }
    
    # ========================================================================
    # 回调管理
    # ========================================================================
    
    def add_load_callback(self, callback: Callable[[Plugin], None]) -> None:
        """添加插件加载回调"""
        self._load_callbacks.append(callback)
    
    def add_unload_callback(self, callback: Callable[[Plugin], None]) -> None:
        """添加插件卸载回调"""
        self._unload_callbacks.append(callback)
    
    def add_error_callback(self, callback: Callable[[Plugin, Exception], None]) -> None:
        """添加插件错误回调"""
        self._error_callbacks.append(callback)
    
    # ========================================================================
    # 插件执行
    # ========================================================================
    
    async def execute_plugin_hook(self, hook_name: str, *args, **kwargs) -> Any:
        """执行插件钩子"""
        return await self.hook_manager.execute_before_hooks(hook_name, {}, *args, **kwargs)
    
    async def shutdown(self) -> None:
        """关闭插件管理器"""

        # 卸载所有插件
        plugin_names = self.registry.list_plugins()
        for plugin_name in reversed(plugin_names):  # 反向卸载
            try:
                await self.unload_plugin(plugin_name)
            except Exception as e:
                self.logger.error(f"卸载插件失败: {plugin_name}, 错误: {e}")

        # 清理上下文
        self.context.cleanup()

    def shutdown_sync(self) -> None:
        """同步关闭插件管理器"""

        # 同步卸载所有插件
        plugin_names = self.registry.list_plugins()
        for plugin_name in plugin_names:
            try:
                plugin = self.registry.get_plugin(plugin_name)
                if plugin:
                    self.registry.unregister(plugin_name)
            except Exception as e:
                self.logger.error(f"同步卸载插件失败 {plugin_name}: {e}")

        # 清理注册表
        self.registry.clear()


# 全局插件管理器
plugin_manager = PluginManager()
